/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework
 * Version 2.10
 * 
 * Table Row Reader Class
 *      Provides a mechanism for safely reading rows and cell values from a table.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Data;

namespace Adaptive.Foundation.Data
{
    /// <summary>
    /// Provides a mechanism for safely reading rows and cell values from a table.
    /// </summary>
    public sealed class TableRowReader : DisposableObjectBase
    {
        /*--------------------------------------------------------------------------------
		 * Private Member Declarations
		 *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// The source data table to read from.
        /// </summary>
        private DataTable _sourceTable;
        /// <summary>
        /// Row index.
        /// </summary>
        private int _currentRowIndex = -1;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
		 *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public TableRowReader(DataTable sourceTable)
            : base()
        {
            _sourceTable = sourceTable;
            if ((sourceTable != null) && (sourceTable.Rows.Count > 0))
                _currentRowIndex = 0;
        }
        /// <summary>
        /// Deallocates internally allocated objectts.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            _currentRowIndex = -1;
            _sourceTable = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
	     * Public Properties
		 *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets a value indicating whether the reader is at the end of the table.
        /// </summary>
        /// <value>
        /// <b>true</b> if all the rows have been read; otherwise, <b>false</b>.
        /// </value>
        public bool Eof
        {
            get { return ((_sourceTable == null) || (_currentRowIndex >= _sourceTable.Rows.Count)); }
        }
        /// <summary>
        /// Gets the number of rows to be read.
        /// </summary>
        /// <value>
        /// The number of rows that may be read from the source table.
        /// </value>
        public int Length
        {
            get
            {
                if (_sourceTable == null)
                    return 0;
                else
                    return _sourceTable.Rows.Count;
            }
        }
        /// <summary>
        /// Gets the current row position value.
        /// </summary>
        /// <value>
        /// The number of the current row being read.
        /// </value>
        public int Position
        {
            get { return _currentRowIndex; }
        }
        /// <summary>
        /// Gets the reference to the current row in the table.
        /// </summary>
        /// <value>
        /// A <see cref="DataRow"/> instance.
        /// </value>
        public DataRow CurrentRow
        {
            get
            {
                if ((_sourceTable == null) || (_currentRowIndex == -1) || (_currentRowIndex > _sourceTable.Rows.Count - 1))
                    return null;
                else
                    return _sourceTable.Rows[_currentRowIndex];
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
		 *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Moves the position of the reader to the first row in the table.
        /// </summary>
        public void MoveFirst()
        {
            if ((_sourceTable != null) && (_sourceTable.Rows.Count > 0))
                _currentRowIndex = 0;
            else
                _currentRowIndex = -1;
        }
        /// <summary>
        /// Moves the position of the reader to the next row in the table.
        /// </summary>
        public void MoveNext()
        {
            if ((_sourceTable != null) && (_sourceTable.Rows.Count > 0))
            {
                _currentRowIndex++;
                if (_currentRowIndex > _sourceTable.Rows.Count)
                    _currentRowIndex = _sourceTable.Rows.Count;
            }
            else
                _currentRowIndex = -1;
        }
        /// <summary>
        /// Moves the position of the reader to the previous row in the table.
        /// </summary>
        public void MovePrevious()
        {
            if ((_sourceTable != null) && (_sourceTable.Rows.Count > 0))
            {
                _currentRowIndex--;
                if (_currentRowIndex < 0)
                    _currentRowIndex = 0;
            }
            else
                _currentRowIndex = -1;
        }
        /// <summary>
        /// Moves the position of the reader to the last row in the table.
        /// </summary>
        public void MoveLast()
        {
            if ((_sourceTable != null) && (_sourceTable.Rows.Count > 0))
                _currentRowIndex = _sourceTable.Rows.Count - 1;
            else
                _currentRowIndex = -1;
        }
        /// <summary>
        /// Attempts to read a string value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnIndex">The ordinal index of the column to be read.</param>
        /// <returns>
        /// The string value of the specified cell, an empty string if the value is null, or <b>null</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public string ReadString(int columnIndex)
        {
            string returnValue = string.Empty;          //Return value.

            //Ensure the position is acvtually valid.
            if ((columnIndex >= 0) && (_sourceTable != null) && (_currentRowIndex > -1) || (_currentRowIndex < _sourceTable.Rows.Count))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnIndex))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (string)_sourceTable.Rows[_currentRowIndex][columnIndex];
                    }
                    catch
                    {
                        returnValue = string.Empty;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = null;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a string value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnName">The name of the column to be read.</param>
        /// <returns>
        /// The string value of the specified cell, an empty string if the value is null, or <b>null</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public string ReadString(string columnName)
        {
            string returnValue = string.Empty;          //Return value.

            //Ensure the position is acvtually valid.
            if ((columnName != null) && (_sourceTable != null) && (columnName.Length > 0) || (_sourceTable.Columns[columnName] != null))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnName))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (string)_sourceTable.Rows[_currentRowIndex][columnName];
                    }
                    catch
                    {
                        returnValue = string.Empty;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = null;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a boolean value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnIndex">The ordinal index of the column to be read.</param>
        /// <returns>
        /// The boolean value of the specified cell, or <b>false</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public bool ReadBoolean(int columnIndex)
        {
            bool returnValue = false;       //Return value.

            //Ensure the position is acvtually valid.
            if ((columnIndex >= 0) && (_sourceTable != null) && (_currentRowIndex > -1) || (_currentRowIndex < _sourceTable.Rows.Count))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnIndex))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (bool)_sourceTable.Rows[_currentRowIndex][columnIndex];
                    }
                    catch
                    {
                        returnValue = false;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = false;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a boolean value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnName">The name of the column to be read.</param>
        /// <returns>
        /// The boolean value of the specified cell, or <b>false</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public bool ReadBoolean(string columnName)
        {
            bool returnValue = false;          //Return value.

            //Ensure the position is acvtually valid.
            if ((columnName != null) && (_sourceTable != null) && (columnName.Length > 0) || (_sourceTable.Columns[columnName] != null))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnName))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (bool)_sourceTable.Rows[_currentRowIndex][columnName];
                    }
                    catch
                    {
                        returnValue = false;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = false;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a short integer value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnIndex">The ordinal index of the column to be read.</param>
        /// <returns>
        /// The boolean value of the specified cell, or <b>0</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public short ReadInt16(int columnIndex)
        {
            short returnValue = 0;       //Return value.

            //Ensure the position is acvtually valid.
            if ((columnIndex >= 0) && (_sourceTable != null) && (_currentRowIndex > -1) || (_currentRowIndex < _sourceTable.Rows.Count))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnIndex))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (short)_sourceTable.Rows[_currentRowIndex][columnIndex];
                    }
                    catch
                    {
                        returnValue = 0;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = 0;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read an integer value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnName">The name of the column to be read.</param>
        /// <returns>
        /// The integer value of the specified cell, or <b>0</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public int ReadInt32(string columnName)
        {
            int returnValue = 0;          //Return value.

            //Ensure the position is acvtually valid.
            if ((columnName != null) && (_sourceTable != null) && (columnName.Length > 0) || (_sourceTable.Columns[columnName] != null))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnName))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = Convert.ToInt32(_sourceTable.Rows[_currentRowIndex][columnName]);
                    }
                    catch
                    {
                        returnValue = 0;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = 0;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a long integer value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnName">The name of the column to be read.</param>
        /// <returns>
        /// The long integer value of the specified cell, or <b>0</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public long ReadInt64(string columnName)
        {
            long returnValue = 0;          //Return value.

            //Ensure the position is acvtually valid.
            if ((columnName != null) && (_sourceTable != null) && (columnName.Length > 0) || (_sourceTable.Columns[columnName] != null))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnName))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (long)_sourceTable.Rows[_currentRowIndex][columnName];
                    }
                    catch
                    {
                        returnValue = 0;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = 0;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a decimal value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnIndex">The ordinal index of the column to be read.</param>
        /// <returns>
        /// The decimal value of the specified cell, or <b>0</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public decimal ReadDecimal(int columnIndex)
        {
            decimal returnValue = 0;       //Return value.

            //Ensure the position is acvtually valid.
            if ((columnIndex >= 0) && (_sourceTable != null) && (_currentRowIndex > -1) || (_currentRowIndex < _sourceTable.Rows.Count))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnIndex))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (decimal)_sourceTable.Rows[_currentRowIndex][columnIndex];
                    }
                    catch
                    {
                        returnValue = 0;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = 0;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a decimal value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnName">The name of the column to be read.</param>
        /// <returns>
        /// The decimal value of the specified cell, or <b>0</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public decimal ReadDecimal(string columnName)
        {
            decimal returnValue = 0;          //Return value.

            //Ensure the position is acvtually valid.
            if ((columnName != null) && (_sourceTable != null) && (columnName.Length > 0) || (_sourceTable.Columns[columnName] != null))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnName))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (decimal)_sourceTable.Rows[_currentRowIndex][columnName];
                    }
                    catch
                    {
                        returnValue = 0;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = 0;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a single value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnIndex">The ordinal index of the column to be read.</param>
        /// <returns>
        /// The single value of the specified cell, or <b>0</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public float ReadSingle(int columnIndex)
        {
            float returnValue = 0;       //Return value.

            //Ensure the position is acvtually valid.
            if ((columnIndex >= 0) && (_sourceTable != null) && (_currentRowIndex > -1) || (_currentRowIndex < _sourceTable.Rows.Count))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnIndex))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (float)_sourceTable.Rows[_currentRowIndex][columnIndex];
                    }
                    catch
                    {
                        returnValue = 0;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = 0;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a single value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnName">The name of the column to be read.</param>
        /// <returns>
        /// The single value of the specified cell, or <b>0</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public float ReadSingle(string columnName)
        {
            float returnValue = 0;          //Return value.

            //Ensure the position is acvtually valid.
            if ((columnName != null) && (_sourceTable != null) && (columnName.Length > 0) || (_sourceTable.Columns[columnName] != null))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnName))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = Convert.ToSingle(_sourceTable.Rows[_currentRowIndex][columnName]);
                    }
                    catch
                    {
                        returnValue = 0;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = 0;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a date value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnIndex">The ordinal index of the column to be read.</param>
        /// <returns>
        /// The date value of the specified cell, or <b>DateTime.MinValue</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public DateTime ReadDateTime(int columnIndex)
        {
            DateTime returnValue = DateTime.MinValue;       //Return value.

            //Ensure the position is acvtually valid.
            if ((columnIndex >= 0) && (_sourceTable != null) && (_currentRowIndex > -1) || (_currentRowIndex < _sourceTable.Rows.Count))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnIndex))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (DateTime)_sourceTable.Rows[_currentRowIndex][columnIndex];
                    }
                    catch
                    {
                        returnValue = DateTime.MinValue;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = DateTime.MinValue;

            return returnValue;
        }
        /// <summary>
        /// Attempts to read a date value from the current row at the specified column position.
        /// </summary>
        /// <param name="columnName">The name of the column to be read.</param>
        /// <returns>
        /// The <see cref="DateTime"/> value of the specified cell, or <b>DateTime.MinValue</b> if 
        /// the position is invalid.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        public DateTime ReadDateTime(string columnName)
        {
            DateTime returnValue = DateTime.MinValue;          //Return value.

            //Ensure the position is acvtually valid.
            if ((columnName != null) && (_sourceTable != null) && (columnName.Length > 0) || (_sourceTable.Columns[columnName] != null))
            {
                //Do not attempt to read a null.
                if (!_sourceTable.Rows[_currentRowIndex].IsNull(columnName))
                {
                    //Try the conversion.
                    try
                    {
                        returnValue = (DateTime)_sourceTable.Rows[_currentRowIndex][columnName];
                    }
                    catch
                    {
                        returnValue = DateTime.MinValue;
                    }
                }
            }
            else
                //Return a null on invalid position read.
                returnValue = DateTime.MinValue;

            return returnValue;
        }
        #endregion

    }
}